package com.hxkj.client.service.taglib.directive;

import com.hxkj.client.service.taglib.config.LableConstant;
import com.hxkj.client.service.taglib.handle.HandingDataBean;
import com.hxkj.utils.TemplateModelUtils;
import com.platform.common.domain.exception.CustomException;
import freemarker.cache.TemplateLoader;
import freemarker.core.Environment;
import freemarker.core._MiscTemplateException;
import freemarker.template.*;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public abstract class AbstractDirective extends HandingDataBean implements TemplateDirectiveModel {

    @Autowired
    private RedisTemplate redisTemplate;

    private static final String SITE_ID = "siteId";

    /**
     * 获取String类型
     **/
    public String getString(String name, Map<String, TemplateModel> params) throws TemplateException, CustomException {
        TemplateModel model = params.get(name);
        if (model == null) {
            return null;
        }
        if (model instanceof TemplateScalarModel) {
            return ((TemplateScalarModel) model).getAsString();
        } else if ((model instanceof TemplateNumberModel)) {
            return ((TemplateNumberModel) model).getAsNumber().toString();
        } else {
            throw new CustomException(name);
        }
    }

    /**
     * 获取long类型
     **/
    public Long getLong(String name, Map<String, TemplateModel> params) throws TemplateException, CustomException {
        TemplateModel model = params.get(name);
        if (model == null) {
            return null;
        }
        if (model instanceof TemplateScalarModel) {
            String s = ((TemplateScalarModel) model).getAsString();
            if (StringUtils.isBlank(s)) {
                return null;
            }
            try {
                return Long.parseLong(s);
            } catch (NumberFormatException e) {
                throw new CustomException(name);
            }
        } else if (model instanceof TemplateNumberModel) {
            return ((TemplateNumberModel) model).getAsNumber().longValue();
        } else {
            throw new CustomException(name);
        }
    }

    /**
     * 获取int类型
     **/
    public Integer getInt(String name, Map<String, TemplateModel> params)
            throws TemplateException, CustomException {
        TemplateModel model = params.get(name);
        if (model == null) {
            return null;
        }
        if (model instanceof TemplateScalarModel) {
            String s = ((TemplateScalarModel) model).getAsString();
            if (StringUtils.isBlank(s)) {
                return null;
            }
            try {
                return Integer.parseInt(s);
            } catch (NumberFormatException e) {
                throw new CustomException();
            }
        } else if (model instanceof TemplateNumberModel) {
            return ((TemplateNumberModel) model).getAsNumber().intValue();
        } else {
            throw new CustomException();
        }
    }

    /**
     * 获取Integer 数组
     **/
    public Integer[] getIntArray(String name, Map<String, TemplateModel> params) throws TemplateException, CustomException {
        String str = getString(name, params);
        if (StringUtils.isBlank(str)) {
            return null;
        }
        String[] arr = StringUtils.split(str, ',');
        Integer[] ids = new Integer[arr.length];
        int i = 0;
        try {
            for (String s : arr) {
                ids[i++] = Integer.valueOf(s);
            }
            return ids;
        } catch (NumberFormatException e) {
            throw new CustomException();
        }
    }

    /**
     * 获取boolean类型
     **/
    public Boolean getBool(String name, Map<String, TemplateModel> params) throws TemplateException, CustomException {
        TemplateModel model = params.get(name);
        if (model == null) {
            return null;
        }
        if (model instanceof TemplateBooleanModel) {
            return ((TemplateBooleanModel) model).getAsBoolean();
        } else if (model instanceof TemplateNumberModel) {
            return !(((TemplateNumberModel) model).getAsNumber().intValue() == 0);
        } else if (model instanceof TemplateScalarModel) {
            String s = ((TemplateScalarModel) model).getAsString();
            // 空串应该返回null还是true呢？
            if (!StringUtils.isBlank(s)) {
                return !(s.equals("0") || s.equalsIgnoreCase("false") || s
                        .equalsIgnoreCase("f"));
            } else {
                return null;
            }
        } else {
            throw new CustomException(name);
        }
    }

    /***
     * 获取set
     * **/
    public static Set<String> getKeysByPrefix(String prefix, Map<String, TemplateModel> params) {
        Set<String> keys = params.keySet();
        Set<String> startWithPrefixKeys = new HashSet<String>();
        if (keys == null) {
            return null;
        }
        for (String key : keys) {
            if (key.startsWith(prefix)) {
                startWithPrefixKeys.add(key);
            }
        }


        return startWithPrefixKeys;
    }

    /**
     * 添加环境变量
     **/
    public static Map<String, TemplateModel> addParamsToVariable(
            Environment env, Map<String, TemplateModel> params)
            throws TemplateException {
        Map<String, TemplateModel> origMap = new HashMap<String, TemplateModel>();
        if (params.size() <= 0) {
            return origMap;
        }
        Set<Map.Entry<String, TemplateModel>> entrySet = params.entrySet();
        String key;
        TemplateModel value;
        for (Map.Entry<String, TemplateModel> entry : entrySet) {
            key = entry.getKey();
            value = env.getVariable(key);
            if (value != null) {
                origMap.put(key, value);
            }
            env.setVariable(key, entry.getValue());
        }
        return origMap;
    }

    /**
     * 删除环境变量
     **/
    public void removeParamsFromVariable(Environment env, Map<String, TemplateModel> params,
                                         Map<String, TemplateModel> origMap) throws TemplateException {
        if (params.size() <= 0) {
            return;
        }
        for (String key : params.keySet()) {
            env.setVariable(key, origMap.get(key));
        }
    }

    private String getFullTemplatePath(Environment environment, @SuppressWarnings("rawtypes") Map params, String templatePath)
            throws MalformedTemplateNameException {
        if (!params.containsKey(templatePath)) {
            throw new MalformedTemplateNameException("missing required parameter '" + templatePath, "'");
        }
        String currentTemplateName = environment.getTemplate().getName();
        final String baseName = FilenameUtils.getPath(currentTemplateName);

        final String targetName = params.get(templatePath).toString();
        final String fullTemplatePath = environment.toFullTemplateName(baseName, targetName);

        return fullTemplatePath;
    }

    private static final String PATH_PARAM = "template";

    private static final String DEFALUT_PATH_PARAM = "default_template";


    /*****
     * 自定义标签include 其他标签
     * *****/
    @Override
    public void execute(Environment environment, @SuppressWarnings("rawtypes") Map params, TemplateModel[] templateModel,
                        TemplateDirectiveBody directiveBody) throws TemplateException, IOException {
        TemplateLoader templateLoader = environment.getConfiguration().getTemplateLoader();
        environment.setVariable("aaa", DefaultObjectWrapperBuilderFactory.getDefaultObjectWrapper().wrap("123"));
        String fullTemplatePath = getFullTemplatePath(environment, params, PATH_PARAM);
        if (templateLoader.findTemplateSource(fullTemplatePath) != null) {
            environment.include(environment.getTemplateForInclusion(fullTemplatePath, null, true));
        } else {
            String defaultFullTemplatePath = getFullTemplatePath(environment, params, DEFALUT_PATH_PARAM);
            if (templateLoader.findTemplateSource(defaultFullTemplatePath) == null) {
                throw new _MiscTemplateException(environment, "Missing template file path:" + defaultFullTemplatePath);
            }
            environment.include(environment.getTemplateForInclusion(defaultFullTemplatePath, null, true));
        }
    }

    /**
     * 获取当前站点
     **/
    protected Long getSiteId(Environment env) throws Exception {

        return (Long) getCustomAttrbute(env, "siteId");
    }

    /**
     * 获取当前分类页数
     **/
    protected Integer getPageNum(Environment env) throws Exception {

        return (Integer) getCustomAttrbute(env, "pageNum");
    }

    /**
     * 获取分类id
     **/
    protected Long getColumnId(Environment env) throws Exception {
        return (Long) getCustomAttrbute(env, "columnId");
    }

    /**
     * 获取tagid
     **/
    protected Long getTagsId(Environment env) throws Exception {
        return (Long) getCustomAttrbute(env, "tagsId");
    }

    /**
     * 获取文章id
     **/
    protected Long getArticleId(Environment env) throws Exception {
        return (Long) getCustomAttrbute(env, "articleId");
    }

    /**
     * 获取站点名称缩写
     **/
    protected String getSiteName(Environment env) throws Exception {
        return (String) getCustomAttrbute(env, "sitename");
    }

    /**
     * 公共型环境配置获取
     **/
    protected Object commonEnv(Environment env, String name) throws Exception {
        TemplateModel templateModel;
        synchronized (Configuration.class) {
            templateModel = env.getConfiguration().getSharedVariable(name);
        }
        return TemplateModelUtils.converBean(templateModel);
    }

    protected String getNote(Environment env) throws Exception {
        return (String) getCustomAttrbute(env, "note");
    }

    protected String getUserToken(Environment env) throws Exception {
        return (String) getCustomAttrbute(env, "userToken");
    }

    protected String getUrlPrefix(Environment env) throws Exception {
        return (String) getCustomAttrbute(env, "urlPrefix");
    }


    /***
     * 可视化拼接方法
     * **/
    protected void print(TemplateDirectiveBody body, Map<String, String> maps, Environment env, String userToken, Map params) throws Exception {
        Writer out = env.getOut();
        Long siteId = getLong(SITE_ID, params) == null ? TemplateModelUtils.converLong(env.getVariable(SITE_ID)) : getLong(SITE_ID, params);
        StringBuffer sb = new StringBuffer();
        Long templetId = getLong("templetId", params);
        sb.append("<!--_").append(LableConstant.CMS_HXKJTAGS).append("_");
        int i = 0;

        String taglibName = "";
        if (templetId == null) {
            for (Map.Entry<String, String> entry : maps.entrySet()) {
                if (i == 0) {
                    taglibName = entry.getKey();
                    sb.append(taglibName);
                    Integer d = add(userToken);
                    sb.append("  num:").append(d + "").append("|");
                } else {
                    String value = entry.getValue();
                    if (StringUtils.isNotEmpty(value) && value != "null")
                        sb.append(entry.getKey()).append(":").append(value).append("|");
                }
                i++;
            }
            if (templetId != null) sb.append("tid").append(":").append(templetId).append("|").toString();
            sb.append("-->");
            out.write(sb.toString());
            body.render(out);
            sb = new StringBuffer();
            //sb.append("<!--_").append(LableConstant.CMS_HXKJTAGS).append("_").append(taglibName).append("-->");
            out.write(sb.toString());
            out.flush();
        } else {
            body.render(out);
        }

    }

    protected Integer add(String userToken) {
        Integer num = (Integer) redisTemplate.opsForValue().get(userToken);
        if (num == null) {
            redisTemplate.opsForValue().set(userToken, 1);
        } else {
            num += 1;
            redisTemplate.opsForValue().set(userToken, num);
        }
        redisTemplate.opsForValue().set("HXKJ_ALL_TEMPLTE", num);
        return num == null ? 1 : num;
    }


    /**
     * 从自定义环境中获取变量
     **/
    public Object getCustomAttrbute(Environment environment, String name) throws Exception {
        if (StringUtils.isEmpty(name)) return null;
        return environment.getCustomAttribute(name);
    }


}
